//---------------------------------------------------------------------------
// <copyright file="RibbonGroupSizeDefinition.cs" company="Microsoft Corporation">
//     Copyright (C) Microsoft Corporation.  All rights reserved.
// </copyright>
//---------------------------------------------------------------------------

namespace Microsoft.Windows.Controls.Ribbon
{
    #region Using declarations

    using System;
    using System.Collections.ObjectModel;
    using System.Collections.Specialized;
    using System.Windows.Markup;

    #endregion

    /// <summary>
    ///   The RibbonGroupSizeDefinition class is used to designate the sizes of Ribbon controls
    ///   within a RibbonGroup, as well as the visual 'collapsed' state of the RibbonGroup.
    /// </summary>
    [ContentProperty("ControlSizeDefinitions")]
    public class RibbonGroupSizeDefinition
    {
        #region Fields

        /// <summary>
        ///   Backing store for the ControlSizeDefinitions property.
        /// </summary>
        private Collection<RibbonControlSizeDefinition> _controlSizeDefinitions;

        /// <summary>
        ///   Backing store for the IsCollapsed property.
        /// </summary>
        private bool _isCollapsed = false;

        /// <summary>
        ///   A value indicating whether the GroupSizeDefinition is sealed.
        /// </summary>
        private bool _isSealed = false;

        #endregion

        #region Public Properties

        /// <summary>
        ///     Gets or sets the ControlSizeDefinitions property. This ordered list of
        ///     ControlSizeDefinitions is representative of a size configuration for the RibbonGroup.
        /// </summary>
        public Collection<RibbonControlSizeDefinition> ControlSizeDefinitions
        {
            get
            {
                if (_controlSizeDefinitions == null)
                {
                    ObservableCollection<RibbonControlSizeDefinition> collection = new ObservableCollection<RibbonControlSizeDefinition>();
                    collection.CollectionChanged += new NotifyCollectionChangedEventHandler(this.OnControlSizeDefinitionsChanged);
                    _controlSizeDefinitions = collection;
                }

                return _controlSizeDefinitions;
            }

            set
            {
                if (_isSealed)
                {
                    // TODO - finalize exception
                    throw new InvalidOperationException("Cannot modify properties of a sealed class: ControlSizeDefinitions property");
                }

                _controlSizeDefinitions = value;
            }
        }

        /// <summary>
        ///     Gets or sets a value indicating whether the RibbonGroup should be in "collapsed" mode.  This
        ///     property must not be changed if the size definition is sealed.  IsCollapsed cannot be set
        ///     to true if the ControlSizeDefinitions are non-empty.
        /// </summary>
        public bool IsCollapsed
        {
            get
            {
                return _isCollapsed;
            }

            set
            {
                if (_isSealed)
                {
                    // TODO - finalize exception
                    throw new InvalidOperationException("Cannot modify properties of a sealed class: ControlSizeDefinitions property");
                }

                if (_controlSizeDefinitions != null && _controlSizeDefinitions.Count > 0 && (bool)value == true)
                {
                    throw new InvalidOperationException("Cannot specify control sizes in collapsed mode");
                }

                _isCollapsed = value;
            }
        }

        #endregion

        #region Internal Methods

        /// <summary>
        ///     Sets a bool indicating whether the RibbonGroupSizeDefinition should be able
        ///     to be modified.
        /// </summary>
        internal void Seal()
        {
            _isSealed = true;
        }

        #endregion

        #region Private Methods

        /// <summary>
        ///     If the ControlSizeDefinitions DependencyProperty changes, we need to check to assure that the
        ///     RibbonGroupSizeDefinition hasn't already been sealed.  We also need to assure we aren't
        ///     moving into an invalid state.
        /// </summary>
        /// <param name="sender">The GroupSizeDefinition whose ControlSizeDefinitions collection has changed.</param>
        /// <param name="e">The event data.</param>
        private void OnControlSizeDefinitionsChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            Collection<RibbonControlSizeDefinition> controlSizeDefinitions = (Collection<RibbonControlSizeDefinition>)sender;

            if (_isSealed)
            {
                // TODO - finalize exception
                throw new InvalidOperationException("Cannot modify properties of a sealed class: ControlSizeDefinitions property");
            }

            // If the IsPopup property is set to true, the default behavior is for the largest variant to appear
            // in the popup.  If the ControlSizeDefinitions property is set while IsPopup is set to true we will throw.
            if (this.IsCollapsed == true && controlSizeDefinitions != null && controlSizeDefinitions.Count > 0)
            {
                // TODO - What exception should we use?
                throw new InvalidOperationException("Cannot specify control sizes in pop-up mode");
            }
        }

        #endregion
    }
}